package sg.edu.nus.iss.vmcs.customer;

import sg.edu.nus.iss.vmcs.store.*;
import sg.edu.nus.iss.vmcs.util.VMCSException;

import java.util.*;

/**
* This class represents the control object that manages the input and storage Coins.
*
* @version 3.0 29/11/2011
* @author  Team 7S - SE19 
*/
public class CoinReceiver {

	private Vector<Coin> coins;
	private int totalInserted;
	
	private TransactionController tranCtrl;
	private StoreController       storeCtrl;

/**
 * This constructor creates an instance of CoinReceiver. It receives the
 * reference for Transaction Controller object as parameter. It also gets the
 * reference for Store Controller object.
 * @param tctrl Transaction Controller
 * @see TransactionController
 * @see StoreController
 */	
	public CoinReceiver(TransactionController tctrl) {
		tranCtrl  = tctrl;
		storeCtrl = tranCtrl.getStoreController();
		coins = new Vector<Coin>();
	}
	
/**
 * This operation gets the Cash Store and returns the reference to an 
 * array of StoreItem 
 * @return Store Items
 */
	public StoreItem[] getCashStore () {
		StoreItem[] items = storeCtrl.getStoreItems(Store.CASH);
		return items;
	}

/**
 * This operation commence receiving a series of Coins. To do this the Coin 
 * Receiver instructs the Coin Input Box to become activated. It also updates 
 * the Total Money Inserted Display on the Customer Panel.
 */	
	public void startReceive(){
		tranCtrl.getCustomerPanel().getCoinInput().setActive(true);
		tranCtrl.getCustomerPanel().getMoneyInserted().setValue("0" + " C");
		totalInserted = 0;
		coins.clear();
	}

/**
 * This operation performs following activities:
 * When a Coin is received the following will occur:
 * 1 The Coin Input Box will be instructed to become deactivated.
 * 2 The weight of the Coin will be sent to the object Coin for it to determine the denomination and value.
 * 3 The Total Money Inserted Display will be updated.
 * 4 If an invalid coin is entered, the Invalid Coin Display will be instructed to display INVALID COIN.
 * 5 The Transaction Controller will be informed to process the current transaction based on the money received.
 * @param weight weight of coin
 * @throws VMCSException Exception 
 */	
	public void receiveCoin(double weight) throws VMCSException{
		//init 
		tranCtrl.getCustomerPanel().getInvalidCoin().setState(false);
		tranCtrl.getCustomerPanel().getCollectCoin().setValue("0" + " C");
		tranCtrl.getCustomerPanel().getCoinInput().setActive(false);
		//validation
		CashStore cashStore = (CashStore)storeCtrl.getStore(Store.CASH);
		Coin coinInserted=cashStore.findCoin(weight);
		if(coinInserted == null){
			tranCtrl.getCustomerPanel().getInvalidCoin().setState(true);
			tranCtrl.getCustomerPanel().getCollectCoin().setValue("Invalid Coin");
			tranCtrl.getCustomerPanel().getCoinInput().setActive(true);
		}else{
			coins.add(coinInserted);
			totalInserted += coinInserted.getValue();
			tranCtrl.getCustomerPanel().getMoneyInserted().setValue(String.valueOf(totalInserted) + " C");
			
			tranCtrl.processMoneyReceived(totalInserted);
		}
	}

/**
 * This operation will activate the Coin Input Box so that further coins can be received. 
 */	
	public void continueReceive(){
		tranCtrl.getCustomerPanel().getCoinInput().setActive(true);
	}

/**
 * Instruct the Cash Store to update its totals and then re-set the 
 * Total Money Inserted Display to zero. 
 * @return boolean state
 * @throws VMCSException Exception for coins
 */	
	public boolean storeCash() throws VMCSException{
		for(Coin coin : coins){
			try {
				tranCtrl.getMainController().getMachineryController().storeCoin(coin);
			} catch (VMCSException e) {
				tranCtrl.terminateFault(this);
				throw new VMCSException("Storing Coins",e.getMessage());
			}
		}
		
		this.coins.clear();
		this.totalInserted = 0;
		tranCtrl.getCustomerPanel().getMoneyInserted().setValue("0" + " C");
		
		
		return true;
	}

/**
 * This operation will deactivate the Coin Input Box in order to stop receiving coins. 
 */	
	public void stopReceive(){
		tranCtrl.getCustomerPanel().getCoinInput().setActive(false);
	}

/**
 * This operation handles the refunding of Coins entered so far to the Customer. 
 */	
	public void refundCash(){
		if(totalInserted == 0)return;
		tranCtrl.getCustomerPanel().getCollectCoin().setValue(String.valueOf(totalInserted) + " C");
		tranCtrl.getCustomerPanel().getMoneyInserted().setValue("0" + " C");
		tranCtrl.getCustomerPanel().getInvalidCoin().setState(false);
	}

/**
 * This operation activates or deactivates the Coin Input Box. 
 * @param active boolean state for active / deactive
 */	
	public void setActive(boolean active){
		
	}
	
/**
 * This operation returns TransactionController object reference during
 * invoke.
 * @return TransactionController
 */	
	public TransactionController getTransactionController() {
		return tranCtrl;
	}
}
